#ifndef __WORD_CONTAINER_H__
#define __WORD_CONTAINER_H__

//#include "./includes/file_types_pack.h"
#include "./includes/file_pointer_pack.h"

namespace invertedindex{


class Word{
	private:
		unsigned int wordId;
		unsigned int wordLength;
		char* word;
	public:
	
		Word(unsigned int wordLengthI, const char* wordI, unsigned int wordIdI){
			this->wordId=wordIdI;
			this->wordLength=wordLengthI;
			this->word = new char[wordLengthI];
			memcpy(this->word, wordI, wordLengthI);
		}

		Word(const Word& wc){
			this->wordId=wc.getWordId();
			std::pair<unsigned int,char*> wrd=wc.getWord();
			this->wordLength=wrd.first;
			this->word = wrd.second;
		}
		virtual ~Word(){
			delete[] word;
		}

		virtual void setFields(const Word& wc){
			delete[] word;
			this->wordId=wc.getWordId();
			std::pair<unsigned int,char*> wrd=wc.getWord();
			this->wordLength=wrd.first;
			this->word = wrd.second;
		}

		void setWordId(unsigned int wordId){this->wordId=wordId;}

		unsigned int getWordId()const {return wordId; }
		unsigned int getWordLength()const {return wordLength; }
		std::pair<unsigned int,char*> getWord()const{
			std::pair<unsigned int,char*> ret(wordLength, NULL);
			ret.second = new char[wordLength];
			memcpy(ret.second,word,wordLength);
			return ret;
		}

		virtual Word* duplicate()const{
			return (new Word(*this));
		}

		int comparate(const Word& wc2)const {
			int ret = 0;
			std::pair<unsigned int, char*> w1=this->getWord();
			std::pair<unsigned int, char*> w2=wc2.getWord();

			if(w1.first<w2.first)
				ret=memcmp ( w1.second, w2.second, w1.first);
			else
				ret=memcmp ( w1.second, w2.second, w2.first);

			if(ret==0){
				if((w2.first)>(w1.first)) 
					ret=-1;
				else {
					if((w2.first)<(w1.first)) 
						ret=1;
					else
						ret=0;
				}
			}
			delete[] w1.second;
			delete[] w2.second;
			return ret;
		}

		virtual std::ostream& toOstream(std::ostream& out)const{
			out << "\t WordId: " << this->wordId << std::endl;
			out << "\t WordLength: " << this->wordLength << std::endl;
			out << "\t Word: ";
			char* temp=word;
			unsigned int i;
			for(i=0; i<this->wordLength; i++){
				out<<*temp;
				temp++;
			}
			out << std::endl;

			return out;
		}

};


class WordContainer : public Word{
	private:
		BlockPointer* bp;

	public:

		WordContainer(unsigned int wordLengthI, const char* wordI, unsigned int wordIdI):Word(wordLengthI,wordI,wordIdI){
			this->bp=NULL;
		}

		WordContainer(const WordContainer& wc):Word(wc){
			this->bp=wc.getBP();
		}
		~WordContainer(){
			delete bp;
		}

		void setFields(const WordContainer& wc){
			Word::setFields(wc);
			delete bp;
			this->bp=wc.getBP();
		}

		BlockPointer* getBP()const {
			if(bp!=NULL)
				return new BlockPointer(*bp); 

			return NULL;
		}

		void setBP(const BlockPointer* bp){
			delete this->bp;
			if(bp!=NULL)
				this->bp=new BlockPointer(*bp); 
			else
				this->bp=NULL;
		}

		void copyBP(const WordContainer& wc){
			delete this->bp;
			this->bp=wc.getBP();
		}

		Word* duplicate()const{
			return (new WordContainer(*this));
		}


		std::ostream& toOstream(std::ostream& out)const{
			Word::toOstream(out);
			if(bp!=NULL)
				bp->toOstream(out);
			else
				out<<"\t\t no File Pointer"<<std::endl;
			return out;
		}

};
/*
class WordContainerOrder{
	public:
		bool operator()(const WordContainer* w1C,const WordContainer* w2C) const{

			bool ret = false;
			std::pair<unsigned int, char*> w1=w1C->getWord();
			std::pair<unsigned int, char*> w2=w2C->getWord();
			int cmp=0;
			if(w1.first<w2.first)
				cmp=memcmp ( w1.second, w2.second, w1.first);
			else
				cmp=memcmp ( w1.second, w2.second, w2.first);
			if((cmp==0)&&((w2.first)>(w1.first))) {ret=true;}
			if(cmp<0)
				ret=true;
			
			delete[] w1.second;
			delete[] w2.second;
			return ret;

		}
};*/

class WordOrder{
	public:
		bool operator()(const Word* w1C,const Word* w2C) const{

			bool ret = false;
			std::pair<unsigned int, char*> w1=w1C->getWord();
			std::pair<unsigned int, char*> w2=w2C->getWord();
			int cmp=0;
			if(w1.first<w2.first)
				cmp=memcmp ( w1.second, w2.second, w1.first);
			else
				cmp=memcmp ( w1.second, w2.second, w2.first);
			if((cmp==0)&&((w2.first)>(w1.first))) {ret=true;}
			if(cmp<0)
				ret=true;
			
			delete[] w1.second;
			delete[] w2.second;
			return ret;

		}
};

}

#endif

